package cn.pedant.SweetAlert;

import com.pnikosis.materialishprogress.ProgressWheel;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorGroup;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.components.element.StateElement;
import ohos.agp.window.dialog.CommonDialog;
import ohos.app.Context;
import ohos.media.image.PixelMap;

public class SweetAlertDialog extends CommonDialog {
    public static final int NORMAL_TYPE = 0;
    public static final int ERROR_TYPE = 1;
    public static final int SUCCESS_TYPE = 2;
    public static final int WARNING_TYPE = 3;
    public static final int CUSTOM_IMAGE_TYPE = 4;
    public static final int PROGRESS_TYPE = 5;

    private AnimatorGroup mModalInAnim;
    private AnimatorGroup mModalOutAnim;
    private String mTitleText;
    private String mContentText;
    private String mCancelText;
    private String mConfirmText;
    private boolean mShowCancel;
    private boolean mShowContent;
    private boolean mCloseFromCancel;

    private ProgressHelper mProgressHelper;
    private int mAlertType;
    private Component mDialogView;
    private Text mTitleTextView;
    private Text mContentTextView;
    private ErrorView mErrorFrame;
    private SuccessView mSuccessFrame;
    private WarningView mWarningFrame;
    private ProgressWheel mProgressFrame;
    private Image mCustomImage;
    private Button mConfirmButton;
    private Button mCancelButton;

    private OnSweetClickListener mCancelClickListener;
    private OnSweetClickListener mConfirmClickListener;

    private StateElement blueButtonBackground;
    private StateElement redButtonBackground;
    private StateElement grayButtonBackground;

    private Element mCustomImgDrawable;

    private Context mContext;

    public static interface OnSweetClickListener {
        public void onClick(SweetAlertDialog sweetAlertDialog);
    }

    public SweetAlertDialog(Context context) {
        this(context, NORMAL_TYPE);
    }

    public SweetAlertDialog(Context context, int alertType) {
        super(context);
        this.mContext = context;
        initStateElement(context);
        mProgressHelper = new ProgressHelper(context);
        mAlertType = alertType;
        Component component = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_alert_dialog, null, false);
        setContentCustomComponent(component);
        setTransparent(true);

        ShapeElement shapeElement = new ShapeElement();
        shapeElement.setRgbColor(new RgbColor(0xffffffff));
        shapeElement.setCornerRadius(dp2px(6, context));
        mDialogView = component.findComponentById(ResourceTable.Id_dialog);
        mDialogView.setBackground(shapeElement);

        mTitleTextView = (Text) component.findComponentById(ResourceTable.Id_title_text);
        mContentTextView = (Text) component.findComponentById(ResourceTable.Id_content_text);
        mErrorFrame = (ErrorView) component.findComponentById(ResourceTable.Id_error_frame);
        mSuccessFrame = (SuccessView) component.findComponentById(ResourceTable.Id_success_frame);
        mWarningFrame = (WarningView) component.findComponentById(ResourceTable.Id_worning_frame);
        mProgressFrame = (ProgressWheel) component.findComponentById(ResourceTable.Id_progressWheel);
        mCustomImage = (Image) component.findComponentById(ResourceTable.Id_custom_image);
        mConfirmButton = (Button) component.findComponentById(ResourceTable.Id_confirm_button);
        mCancelButton = (Button) component.findComponentById(ResourceTable.Id_cancel_button);

        mConfirmButton.setBackground(blueButtonBackground);
        mCancelButton.setBackground(grayButtonBackground);
        mProgressHelper.setProgressWheel(mProgressFrame);

        onClick();

        initAnimatorGroup();
        setTitleText(mTitleText);
        setContentText(mContentText);
        setCancelText(mCancelText);
        setConfirmText(mConfirmText);
        changeAlertType(mAlertType, true);
    }

    private void initStateElement(Context context) {
        blueButtonBackground = new StateElement();
        ShapeElement bluePressedElement = new ShapeElement();
        bluePressedElement.setRgbColor(RgbColor.fromArgbInt(0xff96BFD2));
        bluePressedElement.setCornerRadius(dp2px(6, context));
        ShapeElement blueElement = new ShapeElement();
        blueElement.setRgbColor(RgbColor.fromArgbInt(0xffAEDEF4));
        blueElement.setCornerRadius(dp2px(6, context));
        blueButtonBackground.addState(new int[] {ComponentState.COMPONENT_STATE_PRESSED}, bluePressedElement);
        blueButtonBackground.addState(new int[] {ComponentState.COMPONENT_STATE_EMPTY}, blueElement);

        redButtonBackground = new StateElement();
        ShapeElement redPressedElement = new ShapeElement();
        redPressedElement.setRgbColor(RgbColor.fromArgbInt(0xffCD5B55));
        redPressedElement.setCornerRadius(dp2px(6, context));
        ShapeElement redElement = new ShapeElement();
        redElement.setRgbColor(RgbColor.fromArgbInt(0xffDD6B55));
        redElement.setCornerRadius(dp2px(6, context));
        redButtonBackground.addState(new int[] {ComponentState.COMPONENT_STATE_PRESSED}, redPressedElement);
        redButtonBackground.addState(new int[] {ComponentState.COMPONENT_STATE_EMPTY}, redElement);

        grayButtonBackground = new StateElement();
        ShapeElement grayPressedElement = new ShapeElement();
        grayPressedElement.setRgbColor(RgbColor.fromArgbInt(0xffB6B6B6));
        grayPressedElement.setCornerRadius(dp2px(6, context));
        ShapeElement grayElement = new ShapeElement();
        grayElement.setRgbColor(RgbColor.fromArgbInt(0xffD0D0D0));
        grayElement.setCornerRadius(dp2px(6, context));
        grayButtonBackground.addState(new int[] {ComponentState.COMPONENT_STATE_PRESSED}, grayPressedElement);
        grayButtonBackground.addState(new int[] {ComponentState.COMPONENT_STATE_EMPTY}, grayElement);
    }

    /**
     * hide dialog
     */
    @Override
    public void hide() {
        if (mModalOutAnim != null) {
            mModalOutAnim.setStateChangedListener(
                    new Animator.StateChangedListener() {
                        @Override
                        public void onStart(Animator animator) {}

                        @Override
                        public void onStop(Animator animator) {
                            SweetAlertDialog.super.hide();
                        }

                        @Override
                        public void onCancel(Animator animator) {}

                        @Override
                        public void onEnd(Animator animator) {}

                        @Override
                        public void onPause(Animator animator) {}

                        @Override
                        public void onResume(Animator animator) {}
                    });
            mModalOutAnim.start();
        } else {
            super.hide();
        }
    }

    /**
     * show dialog
     */
    @Override
    public void show() {
        super.show();
        if (mModalInAnim != null) {
            mModalInAnim.setStateChangedListener(
                    new Animator.StateChangedListener() {
                        @Override
                        public void onStart(Animator animator) {}

                        @Override
                        public void onStop(Animator animator) {
                            playAnimation();
                        }

                        @Override
                        public void onCancel(Animator animator) {}

                        @Override
                        public void onEnd(Animator animator) {}

                        @Override
                        public void onPause(Animator animator) {}

                        @Override
                        public void onResume(Animator animator) {}
                    });
            mModalInAnim.start();
        } else {
            playAnimation();
        }
    }

    private void initAnimatorGroup() {
        mModalInAnim = new AnimatorGroup();
        AnimatorGroup.Builder mModalInAnimBuilder = mModalInAnim.build();
        mDialogView.setScaleX(0.7f);
        mDialogView.setScaleY(0.7f);
        AnimatorProperty in1 = new AnimatorProperty(mDialogView);
        in1.scaleX(1.05f).scaleY(1.05f).setDuration(135);
        AnimatorProperty in2 = new AnimatorProperty(mDialogView);
        in2.scaleX(0.95f).scaleY(0.95f).setDuration(105);
        AnimatorProperty in3 = new AnimatorProperty(mDialogView);
        in3.scaleX(1f).scaleY(1).setDuration(60);
        mModalInAnimBuilder.addAnimators(in1).addAnimators(in2).addAnimators(in3);
        mModalOutAnim = new AnimatorGroup();
        AnimatorGroup.Builder mModalOutAnimBuilder = mModalOutAnim.build();
        AnimatorProperty out1 = new AnimatorProperty(mDialogView);
        out1.scaleX(0.6f).scaleY(0.6f).setDuration(150);
        mModalOutAnimBuilder.addAnimators(out1);
    }

    private void playAnimation() {
        if (mAlertType == ERROR_TYPE) {
            mErrorFrame.startAnimator();
        } else if (mAlertType == SUCCESS_TYPE) {
            mSuccessFrame.startAnimator();
        }
    }

    private void changeAlertType(int alertType, boolean fromCreate) {
        mAlertType = alertType;
        // call after created views
        if (mDialogView != null) {
            if (!fromCreate) {
                // restore all of views state before switching alert type
                restore();
            }
            switch (mAlertType) {
                case ERROR_TYPE:
                    mErrorFrame.setVisibility(Component.VISIBLE);
                    break;
                case SUCCESS_TYPE:
                    mSuccessFrame.setVisibility(Component.VISIBLE);
                    // initial rotate layout of success mask
                    break;
                case WARNING_TYPE:
                    mConfirmButton.setBackground(
                            redButtonBackground); // setBackgroundResource(R.drawable.red_button_background);
                    mWarningFrame.setVisibility(Component.VISIBLE);
                    break;
                case CUSTOM_IMAGE_TYPE:
                    setCustomImage(mCustomImgDrawable);
                    break;
                case PROGRESS_TYPE:
                    mProgressFrame.setVisibility(Component.VISIBLE);
                    mConfirmButton.setVisibility(Component.HIDE);
                    break;
            }
            if (!fromCreate) {
                playAnimation();
            }
        }
    }

    private void restore() {
        mCustomImage.setVisibility(Component.HIDE);
        mErrorFrame.setVisibility(Component.HIDE);
        mSuccessFrame.setVisibility(Component.HIDE);
        mWarningFrame.setVisibility(Component.HIDE);
        mProgressFrame.setVisibility(Component.HIDE);
        mConfirmButton.setVisibility(Component.VISIBLE);

        mConfirmButton.setBackground(blueButtonBackground); // setBackgroundResource(R.drawable.blue_button_background);
    }

    private int dp2px(float dp, Context context) {
        return (int) (context.getResourceManager().getDeviceCapability().screenDensity / 160 * dp);
    }

    public int getAlertType() {
        return mAlertType;
    }

    public void changeAlertType(int alertType) {
        changeAlertType(alertType, false);
    }

    public String getTitleText() {
        return mTitleText;
    }

    public SweetAlertDialog setTitleText(String text) {
        mTitleText = text;
        if (mTitleTextView != null && mTitleText != null) {
            mTitleTextView.setText(mTitleText);
        }
        return this;
    }

    public SweetAlertDialog setCustomImage(int resourceId) {
        mCustomImage.setVisibility(Component.VISIBLE);
        mCustomImage.setPixelMap(resourceId);
        return this;
    }

    public SweetAlertDialog setCustomImage(PixelMap pixelMap) {
        mCustomImage.setVisibility(Component.VISIBLE);
        mCustomImage.setPixelMap(pixelMap);
        return this;
    }

    public SweetAlertDialog setCustomImage(Element drawable) {
        mCustomImgDrawable = drawable;
        if (mCustomImage != null && mCustomImgDrawable != null) {
            mCustomImage.setVisibility(Component.VISIBLE);
            mCustomImage.setImageElement(mCustomImgDrawable);
        }
        return this;
    }

    public String getContentText() {
        return mContentText;
    }

    public SweetAlertDialog setContentText(String text) {
        mContentText = text;
        if (mContentTextView != null && mContentText != null) {
            showContentText(true);
            mContentTextView.setText(mContentText);
        }
        return this;
    }

    public boolean isShowCancelButton() {
        return mShowCancel;
    }

    public SweetAlertDialog showCancelButton(boolean isShow) {
        mShowCancel = isShow;
        if (mCancelButton != null) {
            mCancelButton.setVisibility(mShowCancel ? Component.VISIBLE : Component.HIDE);
        }
        return this;
    }

    public boolean isShowContentText() {
        return mShowContent;
    }

    public SweetAlertDialog showContentText(boolean isShow) {
        mShowContent = isShow;
        if (mContentTextView != null) {
            mContentTextView.setVisibility(mShowContent ? Component.VISIBLE : Component.HIDE);
        }
        return this;
    }

    public String getCancelText() {
        return mCancelText;
    }

    public SweetAlertDialog setCancelText(String text) {
        mCancelText = text;
        if (mCancelButton != null && mCancelText != null) {
            showCancelButton(true);
            mCancelButton.setText(mCancelText);
        }
        return this;
    }

    public String getConfirmText() {
        return mConfirmText;
    }

    public SweetAlertDialog setConfirmText(String text) {
        mConfirmText = text;
        if (mConfirmButton != null && mConfirmText != null) {
            mConfirmButton.setText(mConfirmText);
        }
        return this;
    }

    public SweetAlertDialog setCancelClickListener(OnSweetClickListener listener) {
        mCancelClickListener = listener;
        return this;
    }

    public SweetAlertDialog setConfirmClickListener(OnSweetClickListener listener) {
        mConfirmClickListener = listener;
        return this;
    }

    protected void onStart() {
        playAnimation();
    }

    /**
     * The real Dialog.cancel() will be invoked async-ly after the animation finishes.
     */
    public void cancel() {
        dismissWithAnimation(true);
    }

    /**
     * The real Dialog.dismiss() will be invoked async-ly after the animation finishes.
     */
    public void dismissWithAnimation() {
        dismissWithAnimation(false);
    }

    private void dismissWithAnimation(boolean fromCancel) {
        mCloseFromCancel = fromCancel;
        hide();
    }

    private void onClick() {
        mCancelButton.setClickedListener(
                new Component.ClickedListener() {
                    @Override
                    public void onClick(Component component) {
                        if (mCancelClickListener != null) {
                            mCancelClickListener.onClick(SweetAlertDialog.this);
                        } else {
                            hide();
                            dismissWithAnimation();
                        }
                    }
                });

        mConfirmButton.setClickedListener(
                new Component.ClickedListener() {
                    @Override
                    public void onClick(Component component) {
                        if (mConfirmClickListener != null) {
                            mConfirmClickListener.onClick(SweetAlertDialog.this);
                        } else {
                            hide();
                            dismissWithAnimation();
                        }
                    }
                });
    }

    public ProgressHelper getProgressHelper() {
        return mProgressHelper;
    }
}
